#include "at_slm332.h"

#include "t_usart_hw.h"

t_at_t *SLM;

slm_cfg_t slm_cfg;

static EventGroupHandle_t osEvent = NULL;
char temp_buf[64];
uint8_t slm_send_cmd_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len,
                              uint8_t *cmd_Urc_String) {
    //    printf("cb%s\r\n", dataBuf);
    //    printf("slm_send_cmd handle callback OK.%s\r\n", cmd_Urc_String);

    return 0;
}

static void extract_ip(char *response, char *ip) {
    const char *start = strstr(response, "+QIACT:");
    if (start) {
        start = strchr(start, '"');
        if (start) {
            start++;
            const char *end = strchr(start, '"');
            if (end) {
                size_t len = end - start;
                strncpy(ip, start, len);
                ip[len] = '\0';
            }
        }
    }
}
uint8_t slm_send_qact_cmd_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len,
                                   uint8_t *cmd_Urc_String) {
    printf(". %s\n", dataBuf);
    printf("slm_send_cmd handle callback OK  . %s\n", cmd_Urc_String);

    extract_ip((char *)dataBuf, slm_cfg.slm332_net_info_t.slm_4g_ip);

    return 0;
}

static void extract_operator_code(const char *response, char *operator_code) {
    const char *start = strstr(response, "+COPS:");
    if (start) {
        start = strchr(start, '"');
        if (start) {
            start++;
            const char *end = strchr(start, '"');
            if (end) {
                size_t len = end - start;
                strncpy(operator_code, start, len);
                operator_code[len] = '\0';
            }
        }
    }
}

uint8_t slm_send_cops_cmd_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len,
                                   uint8_t *cmd_Urc_String) {
    printf(". %s\n", dataBuf);
    printf("slm_send_cmd handle callback OK  . %s\n", cmd_Urc_String);

    extract_operator_code((char *)dataBuf, slm_cfg.slm332_net_info_t.china_network_name);

    return 0;
}
void extract_iccid(const char *response, char *iccid) {
    const char *start = strstr(response, "+ICCID: ");
    if (start) {
        start += strlen("+ICCID: ");
        const char *end = strchr(start, '\n');
        if (end) {
            size_t len = end - start;
            strncpy(iccid, start, len - 1);
            iccid[len] = '\0';
        }
    }
}
uint8_t slm_send_ccid_cmd_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len,
                                   uint8_t *cmd_Urc_String) {
    printf(". %s\n", dataBuf);
    printf("slm_send_cmd handle callback OK  . %s\n", cmd_Urc_String);

    extract_iccid((char *)dataBuf, slm_cfg.slm332_net_info_t.sim_iccid);

    return 0;
}

static void extract_rssi(const char *response, uint8_t *rssi) {
    const char *start = strstr(response, "+CSQ: ");
    if (start) {
        sscanf(start, "+CSQ: %d,", (int *)rssi);
    }
}
uint8_t slm_send_csq_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len,
                              uint8_t *cmd_Urc_String) {
    printf(". %s\n", dataBuf);
    printf("slm_send_cmd handle callback OK  . %s\n", cmd_Urc_String);
    extract_rssi((char *)dataBuf, &slm_cfg.slm332_net_info_t.db_singal);
    return 0;
}

void extract_imsi(const char *response, char *imsi) {
    const char *start = response;
    while (*start && (*start < '0' || *start > '9')) {
        start++;
    }
    if (*start) {
        const char *end = start;
        while (*end && *end >= '0' && *end <= '9') {
            end++;
        }
        size_t len = end - start;
        strncpy(imsi, start, len);
        imsi[len] = '\0';
    }
}

uint8_t slm_send_imsi_cmd_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len,
                                   uint8_t *cmd_Urc_String) {
    printf(". %s\r\n", dataBuf);
    printf("slm_send_cmd handle callback OK.%s\r\n", cmd_Urc_String);

    extract_imsi((char *)dataBuf, slm_cfg.slm332_net_info_t.sim_imsi);

    return 0;
}

uint8_t bbb_cble[256];

uint8_t slm_init_callback(void *Ptx, uint8_t *dataBuf, uint8_t data_len, uint8_t *cmd_Urc_String) {
    //    t_at_t *me=Ptx;
    // printf("cmd  %s\n", me->buffer->ucr_cmd_buffer);
    printf("slm_init_callback handle OK  . %s\n", cmd_Urc_String);
    return 0;
}

uint8_t bbb[256];

// 硬件接口
uint8_t slm_send_cmd(void *Ptx, uint8_t *dataBuf, uint32_t bufLen) {
    memmove(bbb, dataBuf, bufLen);
    HAL_UART_Transmit(&slm_huart4, bbb, bufLen, 1000);
    // printf("....%s", dataBuf);  // 打印发送到模块的指令 调试使用
    return 0;
}

slm_error_t slm332_send_cmd(char *CMD, uint8_t data_len, char *CMD_UCR, t_at_urc_callback phandle,
                            uint32_t waittime, uint8_t resendCount) {
    T_ErrType ret;
    ret = t_at_cmd_send(SLM, data_len, CMD, CMD_UCR, phandle, waittime, resendCount);
    if (ret == AT_OK) {
        return slm_send_ok;
    } else {
        return slm_send_fail;
    }
}

void slm_power_gpio_set(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOD_CLK_ENABLE();
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
    /*Configure GPIO pin : PD15 */
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    // 开机管脚动作
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
    vTaskDelay(2000);
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
    vTaskDelay(1000);  // 10s开机
}

slm_error_t power_open(void)  // 开机
{
    char temp[20];
    slm_error_t ret;
    slm_power_gpio_set();
    snprintf(temp, sizeof(temp), "AT\r\n");
    int len = strlen(temp);
    ret = slm332_send_cmd(temp, len, "OK", slm_send_cmd_callback, 1000, 2);
    return ret;
}

// 开机slm模块
slm_error_t do_slm_powr_open_ok(uint8_t do_work_re) {
    slm_error_t ret;
    uint8_t retry_count = 0;
    do {
        ret = power_open();
        if (ret == slm_send_fail) {
            retry_count++;
        } else {
            break;
        }
    } while (retry_count < do_work_re);

    if (retry_count == do_work_re) {
        return slm_powr_open_fail;  // 开机失败
    }

    return slm_powr_open_ok;
}
rbuf slm332_ringbuf;

uint16_t get_buffer(char *buffr, uint16_t buffr_size, uint16_t *string_len, const char *cmd) {
    memset(buffr, 0, buffr_size);

    // 将命令复制到目标缓冲区
    snprintf(buffr, buffr_size, "%s", cmd);

    // 计算命令的长度
    *string_len = (uint16_t)strlen(buffr);

    return 0;
}

uint8_t get_mg_mqttc_number(void) { return slm_cfg.slm33_mqttc_num; }
extern void set_mg_mqtt_setup(uint8_t setup) { slm_cfg.slm33_mqttc_num = setup; }
char tmp_cmd[1024];
char tmp_cmd_pbuff[1024];
slm_error_t slm332_creat(slm_cfg_t *slm_cfg) {
    // printf("ssslllmmmm %s","ok");
    slm_error_t ret;

    uint16_t len = 0;
    if (slm_cfg == NULL) {
        return slm_error;
    }
    osEvent = pvPortMalloc(sizeof(EventGroupHandle_t));
    if (osEvent == NULL) {
        return slm_error;
    }
    // 创建一个AT对象  SLM332   10ms超时  重发1次
    SLM = t_at_create(slm_send_cmd, slm_init_callback, 10, 1);
    // 创建OS_lock
    t_at_os_create(SLM, osEvent, t_at_os_init_t, t_at_os_lock_t, t_at_os_unlock_t);
    // 创建循环队列
    t_at_ringbuffer_create(SLM, &slm332_ringbuf, rbuf_init, rbuf_push, rbuf_pop, rbuf_clear,
                           rbuf_is_empty, rbuf_is_full);
    // 等待AT对象初始化完成后--开机slm模块
    ret = do_slm_powr_open_ok(1);
    if (ret == slm_send_fail) {
        slm_cfg->slm_status = slm_power_down;
        return slm_powr_open_ok;  // 开机失败
    }
    // 初始化slm模块
    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QIACT?\r\n");
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 2);

    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QIACT=1\r\n");

    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 2);

    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTCLOSE=1\r\n");
    printf("cmd:%s\r\n", tmp_cmd_pbuff);
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 2);
    // add net info
    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QIACT?\r\n");
    printf("cmd:%s\r\n", tmp_cmd_pbuff);
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "+QIACT:", slm_send_qact_cmd_callback, 1000,
                    2);  // 激活网络PDP get ip

    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+COPS?\r\n");
    printf("cmd:%s\r\n", tmp_cmd_pbuff);
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "+COPS:", slm_send_cops_cmd_callback, 1000, 2);  // 查询网络运营商

    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+ICCID\r\n");
    printf("cmd:%s\r\n", tmp_cmd_pbuff);
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "+ICCID:", slm_send_ccid_cmd_callback, 1000,
                    2);  // 查询SIM卡的CCID

    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+CSQ\r\n");
    printf("cmd:%s\r\n", tmp_cmd_pbuff);
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "+CSQ:", slm_send_csq_callback, 1000, 2);  // 查询信号强度

    snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+CIMI\r\n");
    printf("cmd:%s\r\n", tmp_cmd_pbuff);
    get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
    slm332_send_cmd(tmp_cmd, len, "OK", slm_send_imsi_cmd_callback, 1000,
                    2);  // 查询IMSI  国际移动用户身份码

    /*MQTT_careate first 创建初期MQTT连接不能起来*/

    for (int j = 0; j < get_mg_mqttc_number(); j++) {
        snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTDISC=%d\r\n", j);
        printf("cmd:%s\r\n", tmp_cmd_pbuff);
        get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 1);

        snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTCFG=\"version\",%d,3\r\n", j);
        printf("cmd:%s\r\n", tmp_cmd_pbuff);
        get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 1);
        // // pdpid绑定
        // snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTCFG=\"pdpcid\",%d,%d", i, i+1);
        // printf("cmd:%s\r\n", tmp_cmd_pbuff);
        // get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        // slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 2);
        // keep alive
        snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTCFG=\"keepalive\",%d,60\r\n", j);
        printf("cmd:%s\r\n", tmp_cmd_pbuff);
        get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 1);

        // 如果是aliyun  采用的是SLL TCP 安全连接
        //		snprintf(tmp_cmd_pbuff,sizeof(tmp_cmd_pbuff), "AT+QMTCFG=\"ssl\",1,1");
        //		printf("sssssss:%s\r\n",tmp_cmd_pbuff);
        //		get_buffer(tmp_cmd,sizeof(tmp_cmd)/sizeof(tmp_cmd[0]),&len,tmp_cmd_pbuff);
        //		slm332_send_cmd(tmp_cmd,len, "OK", slm_send_cmd_callback, 1000, 2);
    }
    /*MQTT客户端配置*/
    for (int i = 0; i < get_mg_mqttc_number(); i++) {
        snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTOPEN=%d,\"%s\",%d\r\n", i,
                 slm_cfg->smqtt[i].host, slm_cfg->smqtt[i].port);
        printf("cmd:%s\r\n", tmp_cmd_pbuff);
        get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 1);

        snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTCONN=%d,\"%s\",\"%s\",\"%s\"\r\n", i,
                 slm_cfg->smqtt[i].client_id, slm_cfg->smqtt[i].user_name,
                 slm_cfg->smqtt[i].pass_word);
        printf("cmd:%s\r\n", tmp_cmd_pbuff);
        get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 1);

        snprintf(tmp_cmd_pbuff, sizeof(tmp_cmd_pbuff), "AT+QMTSUB=%d,256,\"%s\",%d\r\n", i,
                 slm_cfg->smqtt[i].subtopic, slm_cfg->smqtt[i].Qos);
        printf("cmd:%s\r\n", tmp_cmd_pbuff);
        get_buffer(tmp_cmd, sizeof(tmp_cmd) / sizeof(tmp_cmd[0]), &len, tmp_cmd_pbuff);
        slm332_send_cmd(tmp_cmd, len, "OK", slm_send_cmd_callback, 1000, 1);
    }
    slm_cfg->slm_status = slm_online;
    return slm_init_ok;
}

uint8_t slm_mqtt_urc_cb(void *Ptx, uint8_t *dataBuf, uint8_t data_len, uint8_t *cmd_UrcString) {
    t_at_t *me = Ptx;
    me->t_send(Ptx, dataBuf, strlen((char *)dataBuf));
    printf("s_cmd.%s\n", dataBuf);
    printf("slm_mqtt_urc_cb handle callback OK  . %s\n", me->buffer->prabuffer);
    return 0;
}

char tmp_cmd1[100];
slm_error_t pslm_mqtt_send_mqttdata(t_at_t *slm332, slm_cfg_t *slm_cfg, uint8_t mqttc_id_t,
                                    t_at_urc_callback slm_send_callback, char *data,
                                    uint16_t datalen) {
    char tmp_cmd_buff[100];
    uint16_t len;
    slm_error_t ret = slm_send_fail;
    memset(tmp_cmd1, 0, sizeof(tmp_cmd1));

    snprintf(tmp_cmd_buff, sizeof(tmp_cmd_buff) / sizeof(tmp_cmd_buff[0]),
             "AT+QMTPUBEX=%d,256,1,%d,\"%s\",%u\r\n", mqttc_id_t, slm_cfg->smqtt[mqttc_id_t].Qos,
             slm_cfg->smqtt[mqttc_id_t].pubtopic, datalen);
    get_buffer(tmp_cmd1, sizeof(tmp_cmd1) / sizeof(tmp_cmd1[0]), &len, tmp_cmd_buff);
    //    printf("send_cmd %s",tmp_cmd1);
    ret = slm332_send_cmd(tmp_cmd1, len, ">", slm_send_callback, 1000, 1);

    ret = slm332_send_cmd(data, datalen, "OK", slm_send_callback, 1000, 1);
    return ret;
}

uint8_t mqtt_urc_cb(void *Ptx, uint8_t *dataBuf, uint8_t data_len, uint8_t *cmd_UrcString) {
    t_at_t *me = Ptx;
    me->t_send(Ptx, dataBuf, strlen((char *)dataBuf));
    printf("s_cmd  . %s\n", dataBuf);
    printf("mqtt_urc_cb handle callback OK  . %s\n", me->buffer->prabuffer);
    return 0;
}
//////////////////////////外部调用接口发送到云端//////////////////////////////
// 最大支持4路
/**
 *
 *  @brief 直接发送数据到MQTTT 会照成阻塞（建议使用队列）
 */
#include "slm_thread.h"
void mqqtc_sned_net_channle_1(uint8_t id, char *data, uint16_t len) {
    queue_MG_send1((uint8_t *)data, len);
}

void mqqtc_sned_net_channle_2(uint8_t id, char *data, uint16_t len) {
    queue_MG_send2((uint8_t *)data, len);
}

void mqqtc_sned_net_channle_3(uint8_t id, char *data, uint16_t len) {
    queue_MG_send3((uint8_t *)data, len);
}

void mqqtc_sned_net_channle_4(uint8_t id, char *data, uint16_t len) {
    queue_MG_send4((uint8_t *)data, len);
}
/// 云端MQTT4路发送的  mqtt brokr----->uart
void mqqtc_sned_other_interface_1(char *data, uint16_t len) {
    /*
     *发送的数据
     */
    // to_send();

    //		  	printf("hex: ");
    //     for (int i = 0; i < len; i++) {
    //        printf("%02X ", data[i]); // 每个字节用2位大写十六进制表示，空格分隔
    //    }
    //     printf(", len=%d\r\n", len);
    mqqtc_sned_net_channle_1(1, data, len);  // 打环
}
void mqqtc_sned_other_interface_2(char *data, uint16_t len) {
    /*
     *发送的数据
     */
    // to_send();
    //	  	printf("hex: ");
    //     for (int i = 0; i < len; i++) {
    //        printf("%02X ", data[i]); // 每个字节用2位大写十六进制表示，空格分隔
    //    }
    //     printf(", len=%d\r\n", len);
    mqqtc_sned_net_channle_2(1, data, len);
}
void mqqtc_sned_other_interface_3(char *data, uint16_t len) {
    /*
     *发送的数据
     */
    // to_send();
    mqqtc_sned_net_channle_3(1, data, len);
    //	printf("data:%s, len=%d\r\n",data, len);
}
void mqqtc_sned_other_interface_4(char *data, uint16_t len) {
    /*
     *发送的数据
     */
    // to_send();
    //		  	printf("hex: ");
    //     for (int i = 0; i < len; i++) {
    //        printf("%02X ", data[i]); // 每个字节用2位大写十六进制表示，空格分隔
    //    }
    //     printf(", len=%d\r\n", len);
    mqqtc_sned_net_channle_4(1, data, len);
}
/// 统一回调 解包  客户端 数据到串口数据
// 不带缓冲区
slm_error_t slm_urc_par(t_at_t *slm332, t_at_urc_callback urc_func, uint8_t *URC_info) {
    t_at_urc_callback_set(slm332, urc_func);
    t_at_parse_polling_rbf(slm332, URC_info);
    return slm_send_ok;
}
// 带缓冲区
/*MG-modbus test*/
/*
 *MQTT解析发送到modbus
 *   : slm332  t_at_t 框架句柄
 *   : urc_func  匹配成功后进行回调  在这里实现replay
 *   : URC_info  要匹配字符串匹配成功后进行回调
 */
slm_error_t mqtt_modbus_urc_decode(t_at_t *slm332, t_at_urc_callback urc_func, uint8_t *URC_info) {
    t_at_urc_callback_set(slm332, urc_func);
    t_at_parse_polling_rbf(slm332, URC_info);
    return slm_send_ok;
}
/**
 * //根据客户端的不同打包数据
 */
